<template>
  <div class="goods-sku">
    <dl v-for="(item, index) in specs" :key="index">
      <dt>{{ item.name }}</dt>
      <dd>
        <template v-for="(tag, i) in item.values" :key="i">
          <img :class='{selected: tag.selected, disabled: tag.disabled}' @click='toggle(tag, item.values)' v-if='tag.picture' :src="tag.picture" alt="">
          <span :class='{selected: tag.selected, disabled: tag.disabled}' @click='toggle(tag, item.values)' v-else>{{tag.name}}</span>
        </template>
      </dd>
    </dl>
  </div>
</template>
<script>
import powerSet from '@/vendor/power-set.js'

// 规格分隔符
const spliter = '※'

// 获取选中的规格的值
const getSelectedValues = (specs) => {
  // 选中的所有的规格数据
  const result = []
  specs.forEach((item, index) => {
    // 获取规格的选中的信息
    const spec = item.values.find(tag => tag.selected)
    if (spec) {
      // 该规格被选中了
      result[index] = spec.name
    } else {
      // 该规格没有选中
      result[index] = undefined
    }
  })
  return result
}

// 生成路径字典
const usePathMap = (skus) => {
  // 路径字典结果
  const result = {}

  skus.forEach(sku => {
    // 过滤掉无效sku数据
    if (sku.inventory === 0) return
    // 获取规格的集合数据：[蓝色，中国，10cm]
    const spec = sku.specs.map(item => item.valueName)
    // 计算当个sku规格的笛卡尔集
    const specSet = powerSet(spec)
    specSet.forEach(item => {
      // 排除空数组
      if (item.length === 0) return
      // 生成字典的key
      const key = item.join(spliter)
      // 把key添加到字典中
      if (result[key]) {
        // 字典中已经存在当前的key
        result[key].push(sku.id)
      } else {
        // 字典中不存在当前的key
        result[key] = [sku.id]
      }
    })
  })
  return result
}

// 控制标签的禁用状态(判断标签是否应该禁用，如果应该应该禁用就给他添加一个disabled属性)
const updateDisabledStatus = (specs, pathMap) => {
  // 需要把规格的每一个标签都判断一遍
  specs.forEach((item, index) => {
    // 每次遍历不同的规格时，重新获取选中的值
    const result = getSelectedValues(specs) // [undefined, undefined, undefined]
    item.values.forEach(tag => {
      if (tag.selected) {
        // 本来是选中的
        return
      } else {
        result[index] = tag.name
      }
      // 判断此时选中的值是否在路径字典里面
      // 把选中的值组合为路径字典的key
      const pathKey = result.filter(tag => tag).join(spliter)
      // const svalue = result.filter(tag => tag) // [黑色]
      // const pathKey = svalue.join(spliter) // 黑色
      // 判断路径字典中是否有该key
      tag.disabled = !pathMap[pathKey]
      // console.log(result)
    })
  })
}

// 根据传入的skuId初始化规格的选中状态
// skuId表示传入的选中的sku规格的id
// specs表示所有的规格数据
// skus表示后端返回的原始的库存数据
const initSkuSeletedStatus = (skuId, specs, skus) => {
  // 获取当前sku信息
  const currentSku = skus.find(item => item.id === skuId)
  specs.forEach(item => {
    currentSku.specs.forEach(tagInfo => {
      // tagInfo表示应该被选中的规格信息
      const tag = item.values.find(tag => tag.name === tagInfo.valueName)
      if (tag) {
        // 该规格需要被选中
        tag.selected = true
      }
    })
  })
}

export default {
  name: 'GoodsSku',
  props: {
    specs: {
      type: Array,
      default: () => []
    },
    skus: {
      type: Array,
      default: () => []
    },
    skuId: {
      type: String,
      default: ''
    }
  },

  setup (props, { emit }) {
    // 如果父组件传递skuId，就控制默认选中标签
    if (props.skuId) {
      initSkuSeletedStatus(props.skuId, props.specs, props.skus)
    }
    // 获取路径字典
    const pathMap = usePathMap(props.skus)
    // console.log(props)
    // 组件初始化时，修改规格的禁用状态
    updateDisabledStatus(props.specs, pathMap)

    // 控制标签的选中和反选(保证仅仅可以选中一个标签)
    const toggle = (tag, list) => {
      // 如果标签是禁用状态，应该阻止执行后续操作
      if (tag.disabled) return
      // 处理当前点击的标签是否选中
      tag.selected = !tag.selected
      // 处理点击当前标签之外的其他标签的情况
      list.forEach((item) => {
        if (item.name !== tag.name) {
          // 其他标签，都编程不选中的状态
          item.selected = false
        }
      })
      // 每次切换选中状态，所有的标签都需要再处理一下禁用状态
      updateDisabledStatus(props.specs, pathMap)

      // 选中规格之后，需要把最终选中的信息传递给父组件
      // 1. 如果选中了所有的规格，就传递正常的数据 skuId 价格  原价  库存 规格文字
      // 2. 如果没有全部选中，就传递空对象 {}
      const selectedValues = getSelectedValues(props.specs).filter(item => item)
      if (selectedValues.length === props.specs.length) {
        // 规格全部选中了
        const result = {}
        // 根据最终选中的规格值，组合成路径字典key
        const pathKey = selectedValues.join(spliter)
        // 根据路径key获取skuId
        const skuId = pathMap[pathKey][0]
        // 根据skuId从skus中获取详细数据
        const skuInfo = props.skus.find(item => item.id === skuId)
        // 准备商品数据
        result.skuId = skuId
        result.price = skuInfo.price
        result.oldPrice = skuInfo.oldPrice
        result.inventory = skuInfo.inventory
        // 拼接规格数据
        // result.specsText = '颜色:黑色;产地:中国;尺寸:10cm'
        // let specsText = ''
        // skuInfo.specs.forEach(item => {
        //   specsText += item.name + ':' + item.valueName + ';'
        // })
        // result.specsText = specsText
        // -------------------------------------
        result.specsText = skuInfo.specs.reduce((result, item) => result + item.name + ':' + item.valueName + ';', '')
        emit('update-info', result)
      } else {
        // 规格没有全部选中
        emit('update-info', {})
      }
    }
    return { toggle }
  }
}
</script>
<style scoped lang="less">
.sku-state-mixin () {
  border: 1px solid #e4e4e4;
  margin-right: 10px;
  cursor: pointer;
  &.selected {
    border-color: @xtxColor;
  }
  &.disabled {
    opacity: 0.6;
    border-style: dashed;
    cursor: not-allowed;
  }
}
.goods-sku {
  padding-left: 10px;
  padding-top: 20px;
  dl {
    display: flex;
    padding-bottom: 20px;
    align-items: center;
    dt {
      width: 50px;
      color: #999;
    }
    dd {
      flex: 1;
      color: #666;
      > img {
        width: 50px;
        height: 50px;
        .sku-state-mixin ();
      }
      > span {
        display: inline-block;
        height: 30px;
        line-height: 28px;
        padding: 0 20px;
        .sku-state-mixin ();
      }
    }
  }
}
</style>
